Skip to content

Conversation

@ItzNotABug
Copy link
Member

@ItzNotABug ItzNotABug commented Jan 14, 2026

What does this PR do?

Changes as per latest server specs, these include -

  1. Updates to Runtime enums
  2. Output is now correctly renamed to ImageFormat
  3. Introduces Backups module for managing Database backups
  4. Introduces Organization module

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • New Features

    • Backups and Organizations services added; health queue monitoring endpoints introduced; optional duration for JWTs; configurable HTTP timeouts.
  • Bug Fixes / Changes

    • Removed several obsolete Deno runtime options; avatar image format enum usage corrected.
  • Documentation

    • Expanded Backups/Organizations/Health docs and examples; SDK compatibility badge updated to "latest"; storage max file size documented as increased.
  • Requirements

    • PHP minimum requirement raised to 8.0.

✏️ Tip: You can customize this high-level summary in your review settings.

@ItzNotABug ItzNotABug self-assigned this Jan 14, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 14, 2026

Warning

Rate limit exceeded

@ItzNotABug has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 52 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 91f96ea and a90c24a.

📒 Files selected for processing (1)
  • tests/Appwrite/Services/HealthTest.php

Walkthrough

Adds two new service classes: Backups (archive, policy, restoration endpoints) and Organizations (delete and deletion-estimation). Client gains timeout and connect-timeout properties with setters and parameter preparation changes. Several service methods changed signatures or parameter handling (Account.createJWT duration, Databases.upsertDocument nullable data, nullable onProgress in Functions/Sites/Storage, Avatars uses ImageFormat). Multiple enums were removed or modified (Output removed; selected Deno runtimes removed from BuildRuntime/Runtime; OAuthProvider MOCK removed; Name adds V1SCREENSHOTS). Extensive documentation and many test updates/examples were added or adjusted.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.72% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Updates: sync as per latest cloud specs' is vague and generic, using non-descriptive language that doesn't convey meaningful information about the specific changes made in the changeset. Provide a more specific and descriptive title that highlights the main changes, such as 'Add Backups and Organizations modules, rename Output to ImageFormat' or 'Sync PHP SDK with latest cloud specifications: modules and enum updates.'
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🤖 Fix all issues with AI agents
In `@docs/backups.md`:
- Line 54: The table row for the parameter archiveId incorrectly describes it as
a "Policy ID"; update the description for archiveId to say "Archive ID" (e.g.,
"Required Archive ID. Choose a custom ID or generate a random ID with
`ID.unique()`. Valid chars are...") so the docs correctly state this endpoint
deletes an archive; adjust only the human-readable label in the archiveId row in
docs/backups.md.
- Line 41: The table cell for the archiveId field contains an unmatched backtick
in the description ("Choose a custom ID`."); edit the archiveId description to
remove the stray backtick or properly wrap the phrase in paired backticks if you
intended inline code (e.g., change to "Choose a custom ID." or "`Choose a custom
ID`."), ensuring the sentence punctuation remains correct and the allowed-chars
sentence is unchanged.
- Line 112: The "policyId" table row contains an unmatched backtick in the
description ("Choose a custom ID`."); locate the "policyId" cell in the
docs/backups.md table (same pattern as the occurrences referenced at lines 41
and 99) and remove the stray backtick so the sentence reads "Choose a custom
ID." (or adjust to proper inline code fencing if that was intended), ensuring no
unmatched backticks remain in that cell.
- Line 99: The "policyId" table row contains an unmatched backtick in the
description ("Choose a custom ID`."); remove the stray backtick so the sentence
reads "Choose a custom ID." and ensure punctuation spacing remains correct;
update the description for the policyId field (policyId) to match the same
corrected wording used earlier (line 41) so there are no stray backticks in the
docs.

In `@docs/examples/account/create-jwt.md`:
- Around line 13-15: In the example calling $account->createJWT, don't use
duration: 0 (it makes the token immediately expired); either remove the duration
parameter to show the default 900s behavior or replace it with a sensible value
such as duration: 1800 (30 minutes) so the example demonstrates a practical JWT
lifetime.

In `@docs/examples/databases/update-document.md`:
- Around line 19-25: The example array entry for the key fullName contains a
curly/smart apostrophe in 'Walter O'Brien' which will cause a PHP parse error;
update the fullName value in the data array (key "fullName") to use a straight
apostrophe or wrap the string in double quotes (e.g., "Walter O'Brien") so the
example parses correctly.

In `@docs/examples/databases/upsert-document.md`:
- Around line 19-25: The 'fullName' array value contains an unescaped single
quote in "O'Brien" causing a PHP parse error; update the 'fullName' entry in the
example data to use either an escaped single quote or double quotes so the
string is valid (e.g., change the value for the 'fullName' key to a properly
quoted string).

In `@docs/examples/tablesdb/update-row.md`:
- Around line 19-25: The example has a PHP parse error: the value for the
fullName entry is a single-quoted string containing an unescaped apostrophe
('Walter O'Brien'); update the fullName value so the string is valid PHP by
either escaping the apostrophe (e.g., Walter O\'Brien) or switching the
surrounding quotes to double quotes ("Walter O'Brien") in the data array entry
for fullName.

In `@docs/examples/tablesdb/update-rows.md`:
- Around line 16-22: The 'fullName' value in the example data array contains an
unescaped apostrophe ("Walter O'Brien") which breaks the PHP single-quoted
string; update the example in the data array so the apostrophe is either escaped
(Walter O\'Brien) or use double quotes for that string ("Walter O'Brien") to
produce valid PHP syntax and avoid a parse error.

In `@docs/examples/tablesdb/upsert-row.md`:
- Around line 19-25: The PHP snippet in the docs has a syntax error because the
value for key 'fullName' is written as 'Walter O'Brien' which contains an
unescaped apostrophe; fix it by either escaping the apostrophe (Walter O\'Brien)
or using double quotes ("Walter O'Brien") for the string in the 'data' array
(the 'fullName' entry), and apply the same fix to the analogous example in
update-rows.md.

In `@docs/health.md`:
- Around line 60-62: The documentation has inconsistent default values for the
health config fields: for "threshold" the description says "Default value is
5000" but the Default column shows 10000, and the same mismatch occurs for
"billing-team-aggregation"; verify the actual default values in the
implementation/config (the canonical source) and then update the docs so the
description and the Default column match — either change the inline description
text to the correct numeric default or update the Default column to the correct
value for both "threshold" and "billing-team-aggregation" entries.

In `@docs/organizations.md`:
- Around line 25-27: The description for the "organizationId" field is
inconsistent; replace "Team ID" with "Organization ID" in the table entry so the
Field Name "organizationId" correctly reads "**Required** Organization ID."
Update the description string associated with organizationId in the
docs/organizations.md table to use "Organization ID" everywhere it currently
says "Team ID."
- Around line 12-14: The table row for the parameter organizationId uses the
wrong description "Team ID"; update that description to "Organization ID" so it
matches the parameter name (organizationId) and avoids confusion in
docs/organizations.md.
🧹 Nitpick comments (23)
tests/Appwrite/IDTest.php (1)

8-11: LGTM! Test correctly validates the new generated ID behavior.

The test appropriately validates that ID::unique() now returns a 20-character generated ID rather than a static string. Consider optionally enhancing the test to also verify:

  • The ID format/pattern (e.g., alphanumeric characters only)
  • Uniqueness across multiple invocations
♻️ Optional: Enhanced test with format and uniqueness validation
 public function testUnique(): void {
     $id = ID::unique();
     $this->assertSame(20, strlen($id));
+    $this->assertMatchesRegularExpression('/^[a-zA-Z0-9]+$/', $id);
+    
+    // Verify uniqueness
+    $id2 = ID::unique();
+    $this->assertNotSame($id, $id2);
 }
composer.json (1)

25-25: Consider using caret versioning for dev dependencies.

Pinning mockery/mockery to exact version 1.6.12 instead of ^1.6.12 prevents automatic patch updates that may include security fixes. For dev dependencies, caret versioning is generally preferred to receive compatible updates.

If this pinning is intentional (e.g., to avoid a known issue in newer versions), consider adding a comment in the file or documentation explaining the rationale.

src/Appwrite/Client.php (1)

196-212: Consider validating timeout values.

The timeout setters accept any int, including negative values. While cURL's behavior with negative timeouts may be to treat them as no timeout or error, explicit validation would provide clearer feedback to SDK users.

💡 Optional: Add validation for non-negative timeouts
 public function setTimeout(int $timeout): Client
 {
+    if ($timeout < 0) {
+        throw new AppwriteException('Timeout must be a non-negative integer');
+    }
     $this->timeout = $timeout;
     return $this;
 }

 public function setConnectTimeout(int $connectTimeout): Client
 {
+    if ($connectTimeout < 0) {
+        throw new AppwriteException('Connect timeout must be a non-negative integer');
+    }
     $this->connectTimeout = $connectTimeout;
     return $this;
 }
tests/Appwrite/Services/StorageTest.php (1)

9-11: Unused imports detected.

The imported enums Compression, ImageGravity, and ImageFormat are not used anywhere in this test file. The test methods call service methods with only required parameters and don't exercise the optional enum parameters.

Consider either:

  1. Removing these unused imports, or
  2. Adding test cases that exercise these enum parameters (e.g., testing createBucket with a Compression value, or getFilePreview with ImageGravity and ImageFormat values)
Option 1: Remove unused imports
 use Appwrite\Client;
 use Appwrite\InputFile;
 use Mockery;
 use PHPUnit\Framework\TestCase;
-use Appwrite\Enums\Compression;
-use Appwrite\Enums\ImageGravity;
-use Appwrite\Enums\ImageFormat;
src/Appwrite/Services/Organizations.php (1)

8-8: Unused import.

InputFile is imported but not used in this service class.

Remove unused import
 use Appwrite\AppwriteException;
 use Appwrite\Client;
 use Appwrite\Service;
-use Appwrite\InputFile;
src/Appwrite/Services/Backups.php (3)

64-66: Inconsistent null handling for optional parameter.

resourceId is assigned directly without a null check, unlike other optional parameters in this file. This could send null to the API even when not intended.

♻️ Suggested fix
         $apiParams = [];
         $apiParams['services'] = $services;
-        $apiParams['resourceId'] = $resourceId;
+
+        if (!is_null($resourceId)) {
+            $apiParams['resourceId'] = $resourceId;
+        }

194-201: Inconsistent null handling between optional parameters.

name and enabled have null checks (lines 194-201), but resourceId on line 197 is assigned directly without a null check. Apply consistent handling across all optional parameters.

♻️ Suggested fix
         if (!is_null($name)) {
             $apiParams['name'] = $name;
         }
-        $apiParams['resourceId'] = $resourceId;
+
+        if (!is_null($resourceId)) {
+            $apiParams['resourceId'] = $resourceId;
+        }
 
         if (!is_null($enabled)) {
             $apiParams['enabled'] = $enabled;
         }

261-269: Inconsistent null handling in updatePolicy.

name, retention, and enabled are assigned directly without null checks, but schedule has a null check. This inconsistency may cause unintended behavior where null values override existing values on the server.

♻️ Suggested fix
         $apiParams = [];
         $apiParams['policyId'] = $policyId;
-        $apiParams['name'] = $name;
-        $apiParams['retention'] = $retention;
+
+        if (!is_null($name)) {
+            $apiParams['name'] = $name;
+        }
+
+        if (!is_null($retention)) {
+            $apiParams['retention'] = $retention;
+        }
 
         if (!is_null($schedule)) {
             $apiParams['schedule'] = $schedule;
         }
-        $apiParams['enabled'] = $enabled;
+
+        if (!is_null($enabled)) {
+            $apiParams['enabled'] = $enabled;
+        }
docs/examples/backups/create-archive.md (1)

13-16: Consider providing a more descriptive example for the services parameter.

The services parameter is currently shown as an empty array, which may not help users understand what values are expected. Consider either:

  • Showing example service names (e.g., ['databases', 'storage'])
  • Adding a comment explaining what services can be included
  • Linking to documentation that lists available service identifiers

This would make the example more helpful for developers implementing backup functionality.

docs/examples/backups/list-restorations.md (1)

13-15: Consider adding query examples for better documentation.

The queries parameter could benefit from example values to help users understand how to filter restorations. For instance:

$result = $backups->listRestorations(
    queries: [
        Query::equal('status', 'completed'),
        Query::limit(10)
    ] // optional
);

This would demonstrate the query capabilities available when listing restorations.

docs/examples/health/get-queue-region-manager.md (1)

13-15: Consider showing a concrete threshold value in the example.

While null is valid, showing an actual integer threshold value would better demonstrate the parameter's purpose:

$result = $health->getQueueRegionManager(
    threshold: 5000 // optional
);

This would help users understand that the threshold represents a numeric limit for queue monitoring.

docs/examples/health/get-queue-threats.md (1)

13-15: Consider omitting the optional parameter or showing a meaningful value.

Explicitly passing null for an optional parameter with a default null value is redundant. Consider either:

  • Omitting it: $result = $health->getQueueThreats();
  • Or showing an example value: threshold: 1000

This would better demonstrate idiomatic usage for documentation readers.

docs/examples/backups/create-policy.md (1)

13-21: Consider using more realistic placeholder values.

The example uses an empty services array and an empty schedule string, which are syntactically valid but not functionally meaningful. Consider using placeholder values that better demonstrate expected usage, such as services: ['database'] and schedule: '0 0 * * *' (daily at midnight), to help developers understand the expected format.

docs/examples/backups/create-restoration.md (1)

13-18: Consider using a more realistic placeholder value for services.

The example uses an empty services array, which won't restore any services. Consider using a placeholder like services: ['database'] to better demonstrate the expected usage pattern.

docs/examples/backups/update-policy.md (1)

17-17: Consider using a realistic schedule value or omitting the parameter.

The empty string for the schedule parameter may confuse users about its expected format. Documentation examples should demonstrate clear, realistic usage.

📝 Suggested improvement

Either provide a realistic cron expression example:

-    schedule: '', // optional
+    schedule: '0 0 * * *', // optional (cron expression for daily at midnight)

Or omit the parameter entirely to show it's optional:

     name: '<NAME>', // optional
     retention: 1, // optional
-    schedule: '', // optional
     enabled: false // optional
CHANGELOG.md (1)

3-6: Expand the changelog entry with specific details.

The current entry "Update SDK as per latest server specs" doesn't help users understand what changed. Based on the PR scope, this version includes significant additions like new Backups and Organizations services, enum updates, and API signature changes.

📝 Suggested improvement
 ## 19.1.1
 
-* Update SDK as per latest server specs
+* Add new `Backups` service with full CRUD operations for archives, policies, and restorations
+* Add new `Organizations` service with delete and estimation methods
+* Add `duration` parameter to `Account::createJWT` method
+* Add new OAuth providers: Okta, Authentik, Oidc
+* Update `Avatars` service to use `ImageFormat` enum instead of `Output`
+* Update `Databases::upsertDocument` to accept optional `data` parameter
+* Add new `Health` service endpoints for queue aggregations
+* Remove deprecated Deno runtime versions from `Runtime` enum
+* Remove `Output` enum (replaced by `ImageFormat` in Avatars)
docs/examples/health/get-queue-billing-project-aggregation.md (1)

13-15: Consider omitting the optional parameter or using a realistic value.

Explicitly passing null for the optional threshold parameter is unusual in documentation examples. Users might wonder if null has special meaning versus omitting the parameter entirely.

📝 Suggested alternatives

Option 1 - Omit the optional parameter:

 $result = $health->getQueueBillingProjectAggregation(
-    threshold: null // optional
 );

Option 2 - Show a realistic threshold value:

 $result = $health->getQueueBillingProjectAggregation(
-    threshold: null // optional
+    threshold: 100 // optional
 );
tests/Appwrite/Services/AvatarsTest.php (1)

9-14: Unused imports: Theme, Timezone, and ImageFormat.

The imports for Theme, Timezone, and ImageFormat on lines 12-14 are added but not used in any test method in this file. Consider removing them to keep imports clean, or add corresponding test cases that utilize these enums.

tests/Appwrite/Services/OrganizationsTest.php (1)

6-6: Unused import.

InputFile is imported but not used in this test file. Consider removing it.

Proposed fix
 use Appwrite\Client;
-use Appwrite\InputFile;
 use Mockery;
tests/Appwrite/Services/TablesDBTest.php (1)

9-11: Unused import: RelationMutate is not used in this test file.

The RelationMutate enum is imported but never referenced in the test methods.

♻️ Proposed fix
 use Appwrite\Enums\RelationshipType;
-use Appwrite\Enums\RelationMutate;
 use Appwrite\Enums\IndexType;
tests/Appwrite/Services/BackupsTest.php (1)

5-8: Unused import: InputFile is not used in this test file.

♻️ Proposed fix
 use Appwrite\Client;
-use Appwrite\InputFile;
 use Mockery;
 use PHPUnit\Framework\TestCase;
tests/Appwrite/Services/FunctionsTest.php (1)

9-13: Unused imports: DeploymentDownloadType and ExecutionMethod are not used.

These enums are imported but not referenced anywhere in the test file.

♻️ Proposed fix
 use Appwrite\Enums\Runtime;
 use Appwrite\Enums\TemplateReferenceType;
 use Appwrite\Enums\VCSReferenceType;
-use Appwrite\Enums\DeploymentDownloadType;
-use Appwrite\Enums\ExecutionMethod;
tests/Appwrite/Services/SitesTest.php (1)

9-14: Unused imports: Adapter and DeploymentDownloadType are not used.

These enums are imported but not referenced anywhere in the test file.

♻️ Proposed fix
 use Appwrite\Enums\Framework;
 use Appwrite\Enums\BuildRuntime;
-use Appwrite\Enums\Adapter;
 use Appwrite\Enums\TemplateReferenceType;
 use Appwrite\Enums\VCSReferenceType;
-use Appwrite\Enums\DeploymentDownloadType;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8738e81 and e406b88.

📒 Files selected for processing (70)
  • .gitignore
  • CHANGELOG.md
  • LICENSE
  • README.md
  • composer.json
  • docs/account.md
  • docs/backups.md
  • docs/examples/account/create-jwt.md
  • docs/examples/avatars/get-screenshot.md
  • docs/examples/backups/create-archive.md
  • docs/examples/backups/create-policy.md
  • docs/examples/backups/create-restoration.md
  • docs/examples/backups/delete-archive.md
  • docs/examples/backups/delete-policy.md
  • docs/examples/backups/get-archive.md
  • docs/examples/backups/get-policy.md
  • docs/examples/backups/get-restoration.md
  • docs/examples/backups/list-archives.md
  • docs/examples/backups/list-policies.md
  • docs/examples/backups/list-restorations.md
  • docs/examples/backups/update-policy.md
  • docs/examples/databases/update-document.md
  • docs/examples/databases/update-documents.md
  • docs/examples/databases/upsert-document.md
  • docs/examples/health/get-queue-billing-project-aggregation.md
  • docs/examples/health/get-queue-billing-team-aggregation.md
  • docs/examples/health/get-queue-priority-builds.md
  • docs/examples/health/get-queue-region-manager.md
  • docs/examples/health/get-queue-threats.md
  • docs/examples/organizations/delete.md
  • docs/examples/organizations/estimation-delete-organization.md
  • docs/examples/tablesdb/update-row.md
  • docs/examples/tablesdb/update-rows.md
  • docs/examples/tablesdb/upsert-row.md
  • docs/health.md
  • docs/organizations.md
  • docs/storage.md
  • src/Appwrite/Client.php
  • src/Appwrite/Enums/BuildRuntime.php
  • src/Appwrite/Enums/Name.php
  • src/Appwrite/Enums/OAuthProvider.php
  • src/Appwrite/Enums/Output.php
  • src/Appwrite/Enums/Runtime.php
  • src/Appwrite/Services/Account.php
  • src/Appwrite/Services/Avatars.php
  • src/Appwrite/Services/Backups.php
  • src/Appwrite/Services/Databases.php
  • src/Appwrite/Services/Functions.php
  • src/Appwrite/Services/Health.php
  • src/Appwrite/Services/Organizations.php
  • src/Appwrite/Services/Sites.php
  • src/Appwrite/Services/Storage.php
  • tests/Appwrite/IDTest.php
  • tests/Appwrite/QueryTest.php
  • tests/Appwrite/Services/AccountTest.php
  • tests/Appwrite/Services/AvatarsTest.php
  • tests/Appwrite/Services/BackupsTest.php
  • tests/Appwrite/Services/DatabasesTest.php
  • tests/Appwrite/Services/FunctionsTest.php
  • tests/Appwrite/Services/GraphqlTest.php
  • tests/Appwrite/Services/HealthTest.php
  • tests/Appwrite/Services/LocaleTest.php
  • tests/Appwrite/Services/MessagingTest.php
  • tests/Appwrite/Services/OrganizationsTest.php
  • tests/Appwrite/Services/SitesTest.php
  • tests/Appwrite/Services/StorageTest.php
  • tests/Appwrite/Services/TablesDBTest.php
  • tests/Appwrite/Services/TeamsTest.php
  • tests/Appwrite/Services/TokensTest.php
  • tests/Appwrite/Services/UsersTest.php
💤 Files with no reviewable changes (4)
  • tests/Appwrite/Services/GraphqlTest.php
  • src/Appwrite/Enums/Runtime.php
  • src/Appwrite/Enums/Output.php
  • src/Appwrite/Enums/BuildRuntime.php
🔇 Additional comments (92)
tests/Appwrite/Services/MessagingTest.php (1)

9-10: LGTM! Test data synchronized with cloud specs.

The changes appropriately align the test mock data with the latest cloud specifications. The status field normalization to "processing" and array syntax adjustments maintain test validity while ensuring consistency with updated API responses.

Also applies to: 25-25, 49-49, 76-76, 101-101, 126-126, 151-151, 177-177, 202-202, 234-234, 251-251, 268-268, 290-290, 314-314, 337-337, 361-361, 384-384, 408-408, 431-431, 455-455, 478-478, 502-502, 525-525, 549-549, 572-572, 597-597, 620-620, 644-644, 667-667, 691-691, 714-714, 738-738, 761-761, 785-785, 808-808, 840-840, 857-857, 874-874, 896-896, 920-920, 943-943, 975-975, 992-992, 1016-1016, 1042-1042

.gitignore (1)

1-2: LGTM!

Standard .gitignore entries for a PHP library. Ignoring vendor/ is correct, and ignoring composer.lock is appropriate for libraries (as opposed to applications) since consumers will generate their own lockfile based on their dependency constraints.

tests/Appwrite/Services/TeamsTest.php (9)

19-33: LGTM!

Syntax correction in test data array is valid. The test properly mocks the client and verifies the list() method response.


35-55: LGTM!

Array syntax fix is correct. Test coverage for create() method looks good.


57-76: LGTM!

Consistent syntax fix applied.


78-98: LGTM!

Syntax correction maintains test integrity.


115-130: LGTM!

Array syntax normalized correctly.


132-159: LGTM!

Syntax fix applied consistently.


161-188: LGTM!

Test data array syntax corrected.


190-218: LGTM!

Consistent with other syntax fixes in this file.


236-265: LGTM!

Final syntax correction in this file applied correctly.

tests/Appwrite/Services/TokensTest.php (4)

19-35: LGTM!

Array syntax correction is valid. Test properly verifies the list() method.


37-58: LGTM!

Syntax fix for createFileToken() test data is correct.


60-80: LGTM!

Consistent array syntax normalization.


82-102: LGTM!

Test data syntax corrected properly.

LICENSE (1)

1-1: LGTM!

Copyright year updated to 2026, which is appropriate for the current year.

composer.json (1)

19-19: Verify PHP version requirement against enum usage.

The concern about PHP version requirement needs confirmation through code inspection. If the codebase uses native PHP enums (which require PHP 8.1+), then >=8.0.0 is insufficient and should be >=8.1.0. Manual verification of enum usage in the codebase is required.

tests/Appwrite/Services/LocaleTest.php (1)

28-28: LGTM!

The syntax fixes consistently clean up array definitions across all test methods by removing erroneous trailing commas. These are valid formatting corrections that improve code consistency.

Also applies to: 44-44, 60-60, 76-76, 92-92, 108-108, 124-124, 140-140

docs/account.md (2)

76-80: LGTM!

The new duration parameter documentation is clear and well-structured. The default value of 900 seconds aligns with the endpoint description stating "The JWT secret is valid for 15 minutes."


568-568: LGTM!

The OAuth provider list expansion to include githubImagine and googleImagine is properly documented.

README.md (2)

9-9: Verify intentional use of "latest" for compatibility statement.

The compatibility statement now reads "compatible with Appwrite server version latest" instead of a specific version. This is vague and could confuse users who need to know exact version compatibility. Consider specifying the actual server version (e.g., 1.8.x or similar) to help users verify their server compatibility.


4-4: LGTM!

The version badge update to 1.8.1 and the description text are appropriate for this SDK sync.

Also applies to: 11-11

tests/Appwrite/Services/AccountTest.php (5)

9-11: LGTM!

The addition of enum imports aligns with the broader SDK refactoring to use type-safe enum values instead of raw strings.


220-222: LGTM!

The migration from string literals to AuthenticatorType::TOTP() enum usage improves type safety and is consistent with the SDK's enum-based approach.

Also applies to: 251-253, 267-269


286-288: LGTM!

Using AuthenticationFactor::EMAIL() instead of a string literal ensures type safety for MFA factor parameters.


1015-1028: LGTM!

The test correctly updates to use OAuthProvider::AMAZON() enum and adjusts the mock expectation to 5 parameters, aligning with apparent changes to the underlying createOAuth2Token method signature.


40-40: LGTM!

The array syntax cleanup across all test methods is consistent and correct, removing trailing commas before closing parentheses.

Also applies to: 70-70, 103-103, 121-121, 151-151, 167-167, 197-197, 214-214, 245-245, 280-280, 324-324, 344-344, 359-359, 374-374, 389-389, 419-419, 450-450, 481-481, 527-527, 548-548, 570-570, 589-589, 646-646, 689-689, 734-734, 779-779, 824-824, 869-869, 913-913, 959-959, 979-979, 1001-1001, 1038-1038, 1060-1060, 1081-1081, 1102-1102, 1124-1124, 1146-1146, 1166-1166

src/Appwrite/Enums/OAuthProvider.php (1)

49-51: LGTM!

The new OAuth providers (MOCKUNVERIFIED, GITHUBIMAGINE, GOOGLEIMAGINE) follow the established singleton-like pattern used throughout this enum class. The lazy initialization and value assignment are consistent with existing providers.

Also applies to: 350-370

tests/Appwrite/QueryTest.php (1)

38-46: Good refactoring: structured assertions over string matching.

Decoding the JSON and asserting on individual fields (attribute, values, method) makes tests more maintainable and provides clearer failure messages when assertions fail. This pattern is consistently applied across all test methods.

src/Appwrite/Client.php (1)

367-385: LGTM!

The prepareParams() method cleanly handles recursive conversion of model objects to arrays for JSON encoding. The toArray() method check is a good duck-typing approach for SDK model compatibility.

src/Appwrite/Services/Account.php (1)

200-216: LGTM!

The optional $duration parameter addition to createJWT() follows the established pattern for optional parameters in this service. The null check ensures the parameter is only included in the API request when explicitly provided.

src/Appwrite/Services/Functions.php (3)

488-488: LGTM: Nullable callback and variable reference fix.

Making $onProgress nullable (line 488) improves API ergonomics. The change on line 555 from $file->getData() to $code->getData() is a correct fix—$code is the InputFile parameter, while $file was an undefined reference.

Also applies to: 555-555


931-931: Fix inconsistent null handling for scheduledAt.

scheduledAt should use a null guard before assignment, matching the pattern used for other optional parameters in createExecution. Sending null to the API causes known issues where executions get stuck in "Scheduled" state and never execute. Use if (!is_null($scheduledAt)) before $apiParams['scheduledAt'] = $scheduledAt; to conditionally include the parameter only when provided.


334-334: Inconsistent null handling for providerRepositoryId.

This optional parameter is assigned directly without a null guard, unlike the recommended pattern for optional parameters. Since providerRepositoryId is optional in the Appwrite Functions API, it should only be added to $apiParams when provided (not null). Verify that all optional parameters in this method follow a consistent pattern using conditional assignment.

src/Appwrite/Services/Sites.php (2)

478-478: LGTM!

The nullable type declaration ?callable $onProgress = null is consistent with the pattern applied across other services in this PR (Functions, Storage).


549-549: Good bug fix: Correct variable used for chunked data.

The change from $file->getData() to $code->getData() correctly references the $code parameter (line 470). This aligns with how the file-path branch handles $code consistently.

src/Appwrite/Services/Storage.php (2)

337-337: LGTM!

The nullable type declaration ?callable $onProgress = null is consistent with the pattern applied to Sites::createDeployment and Functions::createDeployment.


488-491: LGTM!

Conditionally including name only when non-null prevents sending unnecessary null values to the API, consistent with how other optional parameters are handled in this codebase.

docs/storage.md (3)

34-36: LGTM!

Documentation updates reflect the increased maximum file size limit (5GB) and improved compression description formatting.


70-72: LGTM!

Consistent with the bucket creation documentation updates above.


154-157: LGTM!

Field descriptions for the PUT endpoint are now more concise and consistent with other endpoints in the documentation.

src/Appwrite/Services/Organizations.php (2)

10-44: LGTM!

The delete method follows the established patterns in the SDK for DELETE operations.


46-72: Verify the HTTP method with Appwrite API documentation or server implementation.

The docblock describes "Get estimation for deleting an organization" using read operation language, but the implementation uses Client::METHOD_PATCH. Confirm whether the server endpoint actually requires PATCH or if GET is correct.

docs/examples/organizations/estimation-delete-organization.md (1)

1-15: LGTM!

The example correctly demonstrates the usage of estimationDeleteOrganization with proper client initialization and service instantiation.

docs/examples/organizations/delete.md (1)

1-15: LGTM!

The example correctly demonstrates the usage of the delete method with proper client initialization and service instantiation.

src/Appwrite/Services/Databases.php (1)

2247-2271: LGTM!

The $data parameter is now correctly made optional with a null default, and the implementation properly conditionally includes it in the API params. This follows the same pattern used in updateDocument and updateDocuments methods.

src/Appwrite/Services/Health.php (5)

180-209: LGTM!

The new getQueueBillingProjectAggregation method follows the established pattern for queue health checks, with proper null handling for the optional threshold parameter.


211-240: LGTM!

The getQueueBillingTeamAggregation method is consistent with other queue methods in this service.


274-303: LGTM!

The getQueuePriorityBuilds method correctly targets the /health/queue/builds-priority endpoint.


601-630: LGTM!

The getQueueRegionManager method follows the established pattern.


696-725: LGTM!

The getQueueThreats method is correctly implemented and consistent with the other queue health check methods.

src/Appwrite/Services/Backups.php (1)

10-15: LGTM on service class structure.

The Backups service class is well-structured with comprehensive CRUD operations for archives, policies, and restorations. The constructor properly initializes the parent Service class.

docs/examples/backups/list-policies.md (1)

1-15: LGTM!

The example correctly demonstrates usage of the new Backups service's listPolicies method with proper client configuration.

docs/examples/backups/get-policy.md (1)

1-15: LGTM!

The example correctly demonstrates how to retrieve a backup policy using the new Backups service. The code structure is clear and follows the established SDK patterns.

docs/examples/backups/get-restoration.md (1)

1-15: LGTM! Clear and concise documentation example.

The example follows standard SDK documentation patterns with proper client setup, service initialization, and method invocation using named parameters.

docs/examples/backups/delete-policy.md (1)

1-15: LGTM! Consistent with other Backups examples.

The deletePolicy example follows the same clear pattern established in other Backups documentation.

docs/examples/backups/get-archive.md (1)

1-15: LGTM! Consistent Backups service example.

The getArchive example maintains consistency with other Backups documentation and follows SDK conventions.

docs/examples/backups/delete-archive.md (1)

1-15: LGTM!

The example correctly demonstrates the deleteArchive method usage with proper client setup and named parameters.

docs/examples/health/get-queue-priority-builds.md (1)

1-15: LGTM!

The example correctly demonstrates the getQueuePriorityBuilds method with proper handling of the optional threshold parameter.

docs/examples/databases/update-documents.md (1)

16-22: LGTM! Improved example with realistic data.

The documentation now provides a more helpful example by showing actual data fields instead of an empty array, making it clearer how to use the updateDocuments method.

docs/examples/backups/list-archives.md (1)

1-15: LGTM! Clear and well-structured example.

The documentation follows the established SDK pattern and provides a straightforward example for listing backup archives.

tests/Appwrite/Services/AvatarsTest.php (1)

33-34: LGTM on enum migration.

The migration from hard-coded string arguments to enum constants (Browser::AVANTBROWSER(), CreditCard::AMERICANEXPRESS(), Flag::AFGHANISTAN()) improves type safety and consistency across the test suite.

Also applies to: 48-49, 78-79

docs/examples/avatars/get-screenshot.md (1)

7-7: LGTM!

The documentation correctly reflects the migration from Output to ImageFormat enum. The import on line 7 and the usage on line 39 are consistent with the API changes.

Also applies to: 39-39

docs/examples/health/get-queue-billing-team-aggregation.md (1)

1-15: LGTM!

The new documentation example follows the established pattern for health endpoint documentation and correctly demonstrates the usage of getQueueBillingTeamAggregation with the optional threshold parameter.

src/Appwrite/Enums/Name.php (1)

19-19: LGTM!

The new V1SCREENSHOTS enum value follows the established lazy initialization pattern used by all other enum accessors in this class. The implementation is consistent and correctly placed.

Also applies to: 110-116

tests/Appwrite/Services/OrganizationsTest.php (1)

19-48: Tests follow established patterns but provide minimal verification.

The tests correctly verify that the service methods return the mocked client response. This follows the same pattern used in other service tests (e.g., AvatarsTest). However, since all parameters use Mockery::any(), the tests don't verify that the correct HTTP method, path, or parameters are passed to the client.

If stricter verification is desired in the future, consider using Mockery::on() or shouldReceive()->with() to assert expected arguments.

tests/Appwrite/Services/TablesDBTest.php (2)

909-917: Good use of enum constant for type safety.

Using RelationshipType::ONETOONE() instead of a string literal improves type safety and maintainability.


1132-1140: LGTM! Consistent enum usage for index type.

tests/Appwrite/Services/BackupsTest.php (2)

10-17: LGTM! Test setup follows established patterns.

The test class properly initializes the mock client and the Backups service. The structure is consistent with other service tests in this project.


19-273: Comprehensive test coverage for the Backups service.

Tests cover all CRUD operations for archives, policies, and restorations. The mock data structures align with expected API response schemas.

tests/Appwrite/Services/FunctionsTest.php (3)

76-83: LGTM! Proper use of Runtime enum.

Using Runtime::NODE145() instead of a string literal improves type safety.


402-412: LGTM! Consistent enum usage for template deployment.


449-456: LGTM! Consistent enum usage for VCS deployment.

tests/Appwrite/Services/SitesTest.php (4)

78-86: LGTM! Proper use of Framework and BuildRuntime enums.

Using enum constants instead of string literals improves type safety and maintainability.


201-208: LGTM! Consistent enum usage for site update.


409-419: LGTM! Consistent enum usage for template deployment.


456-463: LGTM! Consistent enum usage for VCS deployment.

docs/health.md (1)

91-102: LGTM!

The new builds-priority endpoint documentation is well-structured and consistent with the existing documentation format. The default threshold value (500) is correctly documented in both the description and the Default column.

tests/Appwrite/Services/UsersTest.php (3)

539-542: LGTM!

Good refactoring to use the AuthenticatorType::TOTP() enum instead of the string literal "totp". This improves type safety and makes the test more maintainable.


898-903: LGTM!

Appropriate use of MessagingProviderType::EMAIL() enum replacing the string literal. This aligns with the SDK's type-safe enum pattern.


9-11: Verify that the PasswordHash enum import is used in this file.

AuthenticatorType and MessagingProviderType are used in the test methods, but PasswordHash doesn't appear to be used in the visible changed code. If it's not needed, remove the unused import.

tests/Appwrite/Services/HealthTest.php (6)

9-9: LGTM!

Appropriate import of the Name enum to support type-safe queue name parameters.


238-240: LGTM!

Good refactoring to use Name::V1DATABASE() enum instead of the string literal "v1-database". This maintains consistency with the type-safe enum pattern used throughout the SDK.


124-152: LGTM!

New test methods for getQueueBillingProjectAggregation and getQueueBillingTeamAggregation follow the established testing pattern and provide coverage for the new Health service endpoints.


169-182: LGTM!

Test coverage for the new getQueuePriorityBuilds endpoint is appropriately added following the existing test pattern.


320-333: LGTM!

Test coverage for the new getQueueRegionManager endpoint follows the established pattern.


365-378: LGTM!

Test coverage for the new getQueueThreats endpoint is consistent with the other queue-related tests.

tests/Appwrite/Services/DatabasesTest.php (5)

46-48: LGTM!

Test data structure appropriately updated to include the new type, policies, and archives fields in the database response model. This aligns with the broader changes introducing backup and policy management features.


909-914: LGTM!

Good refactoring to use RelationshipType::ONETOONE() enum instead of a string literal. This maintains type safety and consistency with the SDK's enum pattern.


1388-1394: LGTM!

Appropriate use of IndexType::KEY() enum in the createIndex test method, replacing the string literal with a type-safe enum value.


1253-1257: LGTM!

The test correctly reflects the updated upsertDocument method signature where the data parameter is now optional. Testing with only the required parameters validates the default behavior.


9-11: Verify that RelationMutate enum import is used.

RelationshipType and IndexType are used in the test methods, but RelationMutate doesn't appear to be referenced in the visible changed code. Check if this import is used elsewhere in the file and remove if unused.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| archiveId | string | **Required** Archive ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix unmatched backtick in description.

The description has an unmatched backtick: "Choose a custom ID`." This should be either "Choose a custom ID." or properly paired backticks if code formatting is intended.

📝 Proposed fix
-| archiveId | string | **Required** Archive ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
+| archiveId | string | **Required** Archive ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| archiveId | string | **Required** Archive ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
| archiveId | string | **Required** Archive ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
🤖 Prompt for AI Agents
In `@docs/backups.md` at line 41, The table cell for the archiveId field contains
an unmatched backtick in the description ("Choose a custom ID`."); edit the
archiveId description to remove the stray backtick or properly wrap the phrase
in paired backticks if you intended inline code (e.g., change to "Choose a
custom ID." or "`Choose a custom ID`."), ensuring the sentence punctuation
remains correct and the allowed-chars sentence is unchanged.


| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| archiveId | string | **Required** Policy ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Incorrect parameter description - copy-paste error.

The description for the archiveId parameter incorrectly states "Policy ID" when it should state "Archive ID". This endpoint deletes an archive, not a policy.

📝 Proposed fix
-| archiveId | string | **Required** Policy ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
+| archiveId | string | **Required** Archive ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| archiveId | string | **Required** Policy ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
| archiveId | string | **Required** Archive ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
🤖 Prompt for AI Agents
In `@docs/backups.md` at line 54, The table row for the parameter archiveId
incorrectly describes it as a "Policy ID"; update the description for archiveId
to say "Archive ID" (e.g., "Required Archive ID. Choose a custom ID or generate
a random ID with `ID.unique()`. Valid chars are...") so the docs correctly state
this endpoint deletes an archive; adjust only the human-readable label in the
archiveId row in docs/backups.md.


| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix unmatched backtick in description.

Same issue as line 41: "Choose a custom ID`." has an unmatched backtick.

📝 Proposed fix
-| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
+| policyId | string | **Required** Policy ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
| policyId | string | **Required** Policy ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
🤖 Prompt for AI Agents
In `@docs/backups.md` at line 99, The "policyId" table row contains an unmatched
backtick in the description ("Choose a custom ID`."); remove the stray backtick
so the sentence reads "Choose a custom ID." and ensure punctuation spacing
remains correct; update the description for the policyId field (policyId) to
match the same corrected wording used earlier (line 41) so there are no stray
backticks in the docs.


| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix unmatched backtick in description.

Same issue as lines 41 and 99: "Choose a custom ID`." has an unmatched backtick.

📝 Proposed fix
-| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
+| policyId | string | **Required** Policy ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. |  |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| policyId | string | **Required** Policy ID. Choose a custom ID`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
| policyId | string | **Required** Policy ID. Choose a custom ID. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. | |
🤖 Prompt for AI Agents
In `@docs/backups.md` at line 112, The "policyId" table row contains an unmatched
backtick in the description ("Choose a custom ID`."); locate the "policyId" cell
in the docs/backups.md table (same pattern as the occurrences referenced at
lines 41 and 99) and remove the stray backtick so the sentence reads "Choose a
custom ID." (or adjust to proper inline code fencing if that was intended),
ensuring no unmatched backticks remain in that cell.

Comment on lines +13 to +15
$result = $account->createJWT(
duration: 0 // optional
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reconsider using duration: 0 in the example.

A duration of 0 would create a JWT that expires immediately, which isn't a practical use case. Consider either:

  1. Omitting the parameter entirely to demonstrate the default behavior (900 seconds)
  2. Using a meaningful value like duration: 1800 (30 minutes)
📝 Suggested fix
 $result = $account->createJWT(
-    duration: 0 // optional
+    duration: 1800 // optional, defaults to 900 seconds (15 minutes)
 );

Or simply:

-$result = $account->createJWT(
-    duration: 0 // optional
-);
+$result = $account->createJWT();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$result = $account->createJWT(
duration: 0 // optional
);
$result = $account->createJWT(
duration: 1800 // optional, defaults to 900 seconds (15 minutes)
);
Suggested change
$result = $account->createJWT(
duration: 0 // optional
);
$result = $account->createJWT();
🤖 Prompt for AI Agents
In `@docs/examples/account/create-jwt.md` around lines 13 - 15, In the example
calling $account->createJWT, don't use duration: 0 (it makes the token
immediately expired); either remove the duration parameter to show the default
900s behavior or replace it with a sensible value such as duration: 1800 (30
minutes) so the example demonstrates a practical JWT lifetime.

Comment on lines +16 to +22
data: [
'username' => 'walter.obrien',
'email' => '[email protected]',
'fullName' => 'Walter O'Brien',
'age' => 33,
'isAdmin' => false
], // optional
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Syntax error: Unescaped apostrophe breaks PHP string.

Line 19 has an unescaped apostrophe in 'Walter O'Brien' which will cause a PHP parse error. The single quote terminates the string prematurely.

🐛 Proposed fix
     data: [
         'username' => 'walter.obrien',
         'email' => '[email protected]',
-        'fullName' => 'Walter O'Brien',
+        'fullName' => 'Walter O\'Brien',
         'age' => 33,
         'isAdmin' => false
     ], // optional
🤖 Prompt for AI Agents
In `@docs/examples/tablesdb/update-rows.md` around lines 16 - 22, The 'fullName'
value in the example data array contains an unescaped apostrophe ("Walter
O'Brien") which breaks the PHP single-quoted string; update the example in the
data array so the apostrophe is either escaped (Walter O\'Brien) or use double
quotes for that string ("Walter O'Brien") to produce valid PHP syntax and avoid
a parse error.

Comment on lines +19 to +25
data: [
'username' => 'walter.obrien',
'email' => '[email protected]',
'fullName' => 'Walter O'Brien',
'age' => 33,
'isAdmin' => false
], // optional
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Syntax error: Unescaped apostrophe breaks PHP string.

Same issue as in update-rows.md - the apostrophe in 'Walter O'Brien' on line 22 will cause a PHP parse error.

🐛 Proposed fix
     data: [
         'username' => 'walter.obrien',
         'email' => '[email protected]',
-        'fullName' => 'Walter O'Brien',
+        'fullName' => 'Walter O\'Brien',
         'age' => 33,
         'isAdmin' => false
     ], // optional
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
data: [
'username' => 'walter.obrien',
'email' => '[email protected]',
'fullName' => 'Walter O'Brien',
'age' => 33,
'isAdmin' => false
], // optional
data: [
'username' => 'walter.obrien',
'email' => '[email protected]',
'fullName' => 'Walter O\'Brien',
'age' => 33,
'isAdmin' => false
], // optional
🤖 Prompt for AI Agents
In `@docs/examples/tablesdb/upsert-row.md` around lines 19 - 25, The PHP snippet
in the docs has a syntax error because the value for key 'fullName' is written
as 'Walter O'Brien' which contains an unescaped apostrophe; fix it by either
escaping the apostrophe (Walter O\'Brien) or using double quotes ("Walter
O'Brien") for the string in the 'data' array (the 'fullName' entry), and apply
the same fix to the analogous example in update-rows.md.

docs/health.md Outdated
Comment on lines 60 to 62
| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| threshold | integer | Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000. | 10000 |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documentation inconsistency: description and default value mismatch.

The description states "Default value is 5000" but the Default column shows 10000. This inconsistency could confuse API consumers. Please verify the correct default value and update either the description or the Default column accordingly.

The same issue appears on line 75 for billing-team-aggregation.

🤖 Prompt for AI Agents
In `@docs/health.md` around lines 60 - 62, The documentation has inconsistent
default values for the health config fields: for "threshold" the description
says "Default value is 5000" but the Default column shows 10000, and the same
mismatch occurs for "billing-team-aggregation"; verify the actual default values
in the implementation/config (the canonical source) and then update the docs so
the description and the Default column match — either change the inline
description text to the correct numeric default or update the Default column to
the correct value for both "threshold" and "billing-team-aggregation" entries.

Comment on lines +12 to +14
| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| organizationId | string | **Required** Team ID. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Parameter description is inconsistent with parameter name.

The description says "Team ID" but the parameter is named organizationId. This inconsistency could confuse users. Consider updating the description to "Organization ID" for clarity.

🤖 Prompt for AI Agents
In `@docs/organizations.md` around lines 12 - 14, The table row for the parameter
organizationId uses the wrong description "Team ID"; update that description to
"Organization ID" so it matches the parameter name (organizationId) and avoids
confusion in docs/organizations.md.

Comment on lines +25 to +27
| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| organizationId | string | **Required** Team ID. | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Same inconsistency: "Team ID" should be "Organization ID".

🤖 Prompt for AI Agents
In `@docs/organizations.md` around lines 25 - 27, The description for the
"organizationId" field is inconsistent; replace "Team ID" with "Organization ID"
in the table entry so the Field Name "organizationId" correctly reads
"**Required** Organization ID." Update the description string associated with
organizationId in the docs/organizations.md table to use "Organization ID"
everywhere it currently says "Team ID."

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@docs/account.md`:
- Line 74: The description incorrectly states a fixed 15-minute JWT lifetime;
update the text to state that the JWT lifetime is configurable via the duration
parameter (named "duration") with a default of 15 minutes and a maximum of 3600
seconds (1 hour), so change the sentence mentioning "15 minutes" to reflect that
it's the default and can be extended up to 3600 seconds using the duration
parameter.
🧹 Nitpick comments (1)
CHANGELOG.md (1)

6-9: Consider adjusting nested list indentation.

The nested list items use 4-space indentation, but markdownlint expects 2 spaces for consistency with common Markdown style guides.

📝 Proposed formatting adjustment
 * Update SDK as per latest server specs, these include -
-    * Updates to Runtime enums
-    * `Output` is now renamed to `ImageFormat` - Note that this is a breaking change
-    * Introduces Backups module for managing Database backups
-    * Introduces Organization module
+  * Updates to Runtime enums
+  * `Output` is now renamed to `ImageFormat` - Note that this is a breaking change
+  * Introduces Backups module for managing Database backups
+  * Introduces Organization module
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e406b88 and 91f96ea.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • docs/account.md
  • src/Appwrite/Enums/OAuthProvider.php
  • tests/Appwrite/Services/StorageTest.php
💤 Files with no reviewable changes (1)
  • src/Appwrite/Enums/OAuthProvider.php
🧰 Additional context used
🧬 Code graph analysis (1)
tests/Appwrite/Services/StorageTest.php (3)
src/Appwrite/Enums/Compression.php (1)
  • Compression (7-51)
src/Appwrite/Enums/ImageGravity.php (1)
  • ImageGravity (7-99)
src/Appwrite/Enums/ImageFormat.php (1)
  • ImageFormat (7-83)
🪛 markdownlint-cli2 (0.18.1)
CHANGELOG.md

6-6: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


7-7: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


8-8: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


9-9: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

docs/account.md

76-76: Multiple headings with the same content

(MD024, no-duplicate-heading)

🔇 Additional comments (11)
tests/Appwrite/Services/StorageTest.php (8)

9-11: Imports added for enum types.

The new enum imports align with the SDK's updated type system. The test data currently uses string literals (e.g., "gzip") which is acceptable for mock response data since it represents raw API responses.


53-54: Bucket response data updated with new API fields.

The transformations and totalSize fields are consistently added across all bucket-related tests (createBucket, getBucket, updateBucket). This aligns with the latest cloud API specifications.


26-26: Concise formatting for empty list responses.

Minor formatting improvement that keeps empty arrays on a single line.


172-174: File response data updated with encryption and compression fields.

The encryption and compression fields are consistently added across all file-related tests (createFile, getFile, updateFile). The response structure correctly mirrors the expected API format.


83-84: LGTM!

The test data updates in getBucket are consistent with the other bucket methods.


112-113: LGTM!

The test data updates in updateBucket complete the consistent set of bucket response field additions.


202-204: LGTM!

The getFile test data updates are consistent with createFile.


231-233: LGTM!

The updateFile test data updates complete the consistent set of file response field additions.

CHANGELOG.md (2)

3-10: Changelog entry added; verify versioning strategy for breaking changes.

The past review suggestion has been properly incorporated. However, version 19.1.1 is documented as containing a breaking change (renaming Output to ImageFormat). According to semantic versioning principles, breaking changes typically require a major version increment (e.g., 20.0.0).

Please confirm that the patch version number aligns with your project's versioning strategy.


18-19: LGTM: Improved readability.

The line wrapping improves readability without changing the content.

docs/account.md (1)

76-81: LGTM! Parameter documentation is clear and complete.

The new duration parameter is well-documented with appropriate type, description, default value, and constraints. The default of 900 seconds (15 minutes) and maximum of 3600 seconds (1 hour) provide reasonable flexibility for JWT expiration.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

POST https://cloud.appwrite.io/v1/account/jwts
```

** Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame. **
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update the description to reflect configurable JWT duration.

The description states the JWT is valid for "15 minutes" as a fixed value, but the new duration parameter (lines 76-81) allows customization up to 3600 seconds (1 hour). Consider revising to indicate that the duration is configurable with a default of 15 minutes.

📝 Suggested revision
-** Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame. **
+** Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for the specified duration (default 15 minutes, maximum 1 hour) from its creation and will be invalid if the user will logout in that time frame. **
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

74-74: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


74-74: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

🤖 Prompt for AI Agents
In `@docs/account.md` at line 74, The description incorrectly states a fixed
15-minute JWT lifetime; update the text to state that the JWT lifetime is
configurable via the duration parameter (named "duration") with a default of 15
minutes and a maximum of 3600 seconds (1 hour), so change the sentence
mentioning "15 minutes" to reflect that it's the default and can be extended up
to 3600 seconds using the duration parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants